﻿using System.Collections.Generic;
using System.Diagnostics;
using RibbonLib;
using RibbonLib.Controls.Events;
using RibbonLib.Controls.Properties;
using RibbonLib.Interop;

namespace todo.Ribbon
{
    public class RibbonControl : IRibbonControl
    {
        /// <summary>
        ///   reference for parent ribbon class
        /// </summary>
        protected RibbonUI _ribbonUI;

        /// <summary>
        ///   ribbon control command id
        /// </summary>
        protected uint _commandID;

        /// <summary>
        ///   map of registered properties for this ribbon control
        /// </summary>
        protected Dictionary<PropertyKey, IPropertiesProvider> _mapProperties =
                new Dictionary<PropertyKey, IPropertiesProvider>();

        /// <summary>
        ///   map of registered events for this ribbon control
        /// </summary>
        protected Dictionary<ExecutionVerb, IEventsProvider> _mapEvents =
                new Dictionary<ExecutionVerb, IEventsProvider>();

        /**/
        private bool _enabled = true;

        public bool Enabled
        {
            get { return _enabled; }
            set
            {
                if (_enabled == value)
                {
                    return;
                }
//                if (_commandID == 1070)
//                {
//                    Debug.Print("### invalidating paste button with enabled: " + value);
//                }

                _enabled = value;
//                var boolValue = PropVariant.FromObject(value);
//                _ribbonUI.Framework.SetUICommandProperty(
//                    _commandID, ref RibbonProperties.Enabled, ref boolValue);
                _ribbonUI.Framework.InvalidateUICommand(_commandID, Invalidations.Property,
                        PropertyKeyRef.From(RibbonProperties.Enabled));
            }
        }

        /// <summary>
        ///   BaseRibbonControl ctor
        /// </summary>
        /// <param name="ribbon"> parent ribbon </param>
        /// <param name="commandID"> command id attached to this control </param>
        public RibbonControl(RibbonUI ribbonUI, uint commandID)
        {
            _ribbonUI = ribbonUI;
            _commandID = commandID;

            _ribbonUI.AddRibbonControl(this);
        }

        /// <summary>
        ///   Register a properties provider with this ribbon control
        /// </summary>
        /// <param name="propertiesProvider"> properties provider </param>
        protected void AddPropertiesProvider(IPropertiesProvider propertiesProvider)
        {
            foreach (var propertyKey in propertiesProvider.SupportedProperties)
            {
                _mapProperties[propertyKey] = propertiesProvider;
            }
        }

        /// <summary>
        ///   Register an events provider with this ribbon control
        /// </summary>
        /// <param name="eventsProvider"> events provider </param>
        protected void AddEventsProvider(IEventsProvider eventsProvider)
        {
            foreach (var verb in eventsProvider.SupportedEvents)
            {
                _mapEvents[verb] = eventsProvider;
            }
        }

        #region IRibbonControl Members

        public uint CommandID
        {
            get { return _commandID; }
        }

        /// <summary>
        ///   Handles IUICommandHandler.Execute function for this ribbon control
        /// </summary>
        /// <param name="verb"> the mode of execution </param>
        /// <param name="key"> the property that has changed </param>
        /// <param name="currentValue"> the new value of the property that has changed </param>
        /// <param name="commandExecutionProperties"> additional data for this execution </param>
        /// <returns> Returns S_OK if successful, or an error value otherwise </returns>
        public virtual HRESULT Execute(ExecutionVerb verb, PropertyKeyRef key,
                                       PropVariantRef currentValue,
                                       IUISimplePropertySet commandExecutionProperties)
        {
            // check if verb is registered with this ribbon control
            if (_mapEvents.ContainsKey(verb))
            {
                // find events provider
                var eventsProvider = _mapEvents[verb];

                // delegates execution to events provider
                return eventsProvider.Execute(verb, key, currentValue, commandExecutionProperties);
            }

            Debug.WriteLine(string.Format("Class {0} does not support verb: {1}.", GetType(), verb));
            return HRESULT.E_NOTIMPL;
        }

        /// <summary>
        ///   Handles IUICommandHandler.UpdateProperty function for this ribbon control
        /// </summary>
        /// <param name="key"> The Property Key to update </param>
        /// <param name="currentValue"> A pointer to the current value for key. This parameter can be NULL </param>
        /// <param name="newValue"> When this method returns, contains a pointer to the new value for key </param>
        /// <returns> Returns S_OK if successful, or an error value otherwise </returns>
        public virtual HRESULT UpdateProperty(ref PropertyKey key, PropVariantRef currentValue,
                                              ref PropVariant newValue)
        {
            // check if property is registered with this ribbon control
            if (_mapProperties.ContainsKey(key))
            {
                // find property provider
                var propertiesProvider = _mapProperties[key];

                // delegates execution to property provider
                return propertiesProvider.UpdateProperty(ref key, currentValue, ref newValue);
            }

            /**/
            if (key == RibbonProperties.Enabled)
            {
//                Debug.Print("@@@@@@@ update cmd enabled: " + _enabled + " @" + _commandID);
                newValue.SetBool(_enabled);
                return HRESULT.S_OK;
            }


//            Debug.WriteLine(string.Format("Class {0} does not support property: {1}.", GetType(),
//                                          RibbonProperties.GetPropertyKeyName(ref key)));
            return HRESULT.S_OK;
        }

        #endregion
    }
}